/**
 * 此文件中新添加的方法有。
 * Array.removeOne(obj)			移除数组中的第一个obj元素,数组中有obj并且执行了移除操作返回true，否则返回false
 * Array.removeAll(obj)			移除数组中所有的obj元素，数组中有obj并且执行了移除操作返回true，否则返回false
 * String.startsWith(str)		判断字符串是否是以字符串str开头的，是就返回true，否则返回false
 * String.endWith(str)			判断字符串是否是以字符串str结束的，是就返回true，否则返回false
 * Date.format(format)			格式化日期对象，返回格式化后的日期字符串
 * $.cookie(name,value[,options])	扩展jquery，给jquery添加写cookie的方法
 * $.cookie(name)				扩展jquery，给jquery添加获取cookie的方法
 * $.isNotBlack(str)			扩展jquery，给jqeruy添加字符串判断非空方法isNotBlack，当str为undefined，null，空白字符返回false，否则返回true
 * $.getStringLengthByBytes(str) 扩展jquery，给jqery添加获取字符串字节的长度方法getStringLengthByBytes，返回字符串的字节长度。
 * $.isInt(str)					扩展jquery，给jquery添加判断字符串是否是一个整数格式的字符串，是就返回true，否则返回false
 * $.toFix(value, precision)	扩展jquery，给jquery添加精确小数位数的方法，value小数值，precision精确的小数点后的位数，返回精确后的小数值。
 * $.exists(select)				扩展jquery，给jquery添加判断document上是否存在select选择器的元素，存在就返回true，否则就返回false。
 *
 * 图片瀑布流的使用
 * 	var photos = new InitImage({
 * 		id: "wrap",
 * 		createWaiting: function() {},
 *
 * 	});
 * 	参数：
 * 	id 是图片的外面的容器id。
 * 	createWaiting 蒙层函数，在图片没有加载之前的蒙层回调函数
 * 	注：
 * 		1.用div代替img标签，InitImage会自动添加img标签。
 * 		2.div中必须有imageloader,img-src,img-width,img-height,img-class这些属性。
 * img-src是图片的路径地址，img-width和img-height是图片宽高比的值，img-class是成产的img标签的class
 *
 * 滚动加载数据
 * $.scrollToLoad(id, callback);
 * 参数：
 * 	id 添加数据的容器id
 * 	calllback 滚动的最后以后触发事件执行回调函数
 */
/*global define window document navigator InitImage:true*/
define([
    'jquery', 'masonry'
], function($, Masonry) {

    //浏览器判断
    $.browser = {};
    $.browser.mozilla = /firefox/.test(navigator.userAgent.toLowerCase());
    $.browser.webkit = /webkit/.test(navigator.userAgent.toLowerCase());
    $.browser.opera = /opera/.test(navigator.userAgent.toLowerCase());
    $.browser.msie = /msie/.test(navigator.userAgent.toLowerCase());
    $.browser.iphone = /iphone/.test(navigator.userAgent.toLowerCase());

    //扩展js中的数组对象Array
    Array.prototype.removeOne = function(obj) {
        var a = this.indexOf(obj);
        if (a >= 0) {
            this.splice(a, 1);
            return true;
        }
        return false;
    };

    Array.prototype.removeAll = function(obj) {
        var a = this.indexOf(obj);
        while (a >= 0) {
            this.splice(a, 1);
            a = this.indexOf(obj);
            if (a < 0) {
                return true;
            }
        }
        return false;
    };

    Array.prototype.uniqueSame = function() {
        this.sort();
        var re = [this[0]];
        for (var i = 1; i < this.length; i++) {
            if (this[i] !== re[re.length - 1]) {
                re.push(this[i]);
            }
        }
        return re;
    };

    //扩展js中的字符串对象String
    String.prototype.startsWith = function(str) {
        return this.slice(0, str.length) == str;
    };

    String.prototype.endWidth = function(str) {
        return this.slice(this.length - str.length, this.length) == str;
    };

    //扩展js中的日期对象Date
    Date.prototype.format = function(format) {
        var o = {
            "M+": this.getMonth() + 1, //month
            "d+": this.getDate(), //day
            "h+": this.getHours(), //hour
            "m+": this.getMinutes(), //minute
            "s+": this.getSeconds(), //second
            "q+": Math.floor((this.getMonth() + 3) / 3), //quarter
            "S": this.getMilliseconds() //millisecond
        };
        if (/(y+)/.test(format)) {
            format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
        }
        for (var k in o) {
            if (new RegExp("(" + k + ")").test(format)) {
                format = format.replace(RegExp.$1, RegExp.$1.length == 1
                    ? o[k]
                    : ("00" + o[k]).substr(("" + o[k]).length));
            }
        }
        return format;
    };

    /**
	 * $.cookie(name);获取key为那么的cookie值
	 * $.cookie(name, value [, options]);设置cookie
	 * @param {Object} name 	cookie的名字
	 * @param {Object} value	cookie的值
	 * @param {Object} options	options对象有三个属性：1.expires--是数字就表示多少天，或是一个date对象表示过期时间。
	 * 			2.path--路径在此路径获子路径下才可获取cookie值。3.domain--指定的网站发送请求才携带cookie。值网站地址。
	 * 			4.secure--是否使用安全套接字层 (SSL)（即仅通过 HTTPS）传输 Cookie，值为true或false。
	 */
    $.extend($, {
        cookie: function(name, value, options) {
            if (typeof value != 'undefined') { // name and value given, set cookie
                options = options || {};
                if (value === null) {
                    value = '';
                    options.expires = new Date(0);
                }
                var expires = '';
                if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
                    var date;
                    if (typeof options.expires == 'number') {
                        date = new Date();
                        date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
                    } else {
                        date = options.expires;
                    }
                    expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
                }
                // CAUTION: Needed to parenthesize options.path and options.domain
                // in the following expressions, otherwise they evaluate to undefined
                // in the packed version for some reason...
                var path = options.path
                    ? '; path=' + (options.path)
                    : '';
                var domain = options.domain
                    ? '; domain=' + (options.domain)
                    : '';
                var secure = options.secure
                    ? '; secure'
                    : '';
                document.cookie = [
                    name,
                    '=',
                    encodeURIComponent(value),
                    expires,
                    path,
                    domain,
                    secure
                ].join('');
                //alert(document.cookie);
            } else { // only name given, get cookie
                var cookieValue = null;
                if (document.cookie && document.cookie != '') {
                    var cookies = document.cookie.split(';');
                    for (var i = 0; i < cookies.length; i++) {
                        var cookie = $.trim(cookies[i]);
                        // Does this cookie string begin with the name we want?
                        if (cookie.substring(0, name.length + 1) == (name + '=')) {
                            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                            break;
                        }
                    }
                }
                return cookieValue;
            }
        },
        // 非空检查
        isNotBlank: function(str) {
            if (typeof str == "undefined" || str == null) {
                return false;
            }
            return this.getStringLengthByBytes($.trim(str)) != 0;
        },
        // 判断是否是数组对象
        isArray: function(v) {
            return toString.apply(v) === '[object Array]';
        },
        //返回byte长度
        getStringLengthByBytes: function(str) {
            if (typeof(str) == 'number') {
                str += "";
            }
            return str.replace(/[^\x00-\xFF]/g, '**').length;
        },

        // 把html字符转成js字符
        html2jsstr: function(str) {
            return str.replace(/<br\/>/g, "\r\n").replace(/<br>/g, "\r\n").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&apos;/g, "'").replace(/&quot;/g, "\"");
        },

        // 把js字符转成html字符
        jsstr2html: function(str) {
            return str.replace(/&/g, "&amp;").replace(/ /g, "&nbsp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;").replace(/\r\n/g, "<br/>").replace(/\r/g, "<br/>").replace(/\n/g, "<br/>");
        },

        //判断输入是否是一个整数
        isInt: function(str) {
            var result = str.match(/^(-|\+)?\d+$/);
            if (result == null)
                return false;
            return true;
        },

        // 格式化浮点数
        // value待格式化的浮点数
        // precision保留小数位
        toFix: function(value, precision) {
            var power = Math.pow(10, precision || 0);
            return String(Math.round(value * power) / power);
        },

        exists: function(selector) {
            return ($(selector).length > 0);
        },

        isFunc: function(func) {
            return func && typeof func == 'function';
        }
    });

    window.InitImage = function(param) {
        this.params = $.extend({}, param);
        this.$contentElements = null;
        this.masonry = null;
        this.refresh();
    };

    InitImage.prototype.refresh = function() {
        this.$contentElements = $("[imageloader]");
        this.initDom();
        this.bindEvents(this.$contentElements.find("img"));
        this.after(this.$contentElements.find("img"));
        $(this.$contentElements.find("img")).unveil(100, "content-body");
    };

    InitImage.prototype.initDom = function() {
        var _this = this;
        this.$contentElements.each(function() {
            var $content = $(this);
            //获取基本元素属性
            var imgSrc = $content.attr("img-src");
            var imgWidth = $content.attr("img-width");
            var imgHeight = $content.attr("img-height");
            var imgClass = $content.attr("img-class");

            //计算缩放后的img宽高
            var contentWidth = $content.width();
            var contentHeight = parseInt(imgHeight) * contentWidth / parseInt(imgWidth);

            //创建img元素
            var img_src = "images/error.jpg";
            var img = "<img class='" + imgClass + " default_img' src='' data-src='" + imgSrc + "' style='border: 1px solid #888; width: " + contentWidth + "px;height:" + contentHeight + "px;'/>";
            $content.html(img);

            //创建蒙层
            var waiting = null;
            if (_this.params.createWaiting && typeof _this.params.createWaiting == "function") {
                waiting = this.params.createWaiting.call(this, {});
            } else {
                // 默认蒙层
                //				waiting = $("<div class='spinner'><div class='rect0'></div><div class='rect1'></div><div class='rect2'></div></div>");
                //				waiting.css({
                //					"margin-top": ((contentHeight - 50) / 2) + "px",
                //					"margin-left": ((contentWidth - 50) / 2) + "px"
                //				});
            }
            $content.prepend(waiting);
        });
    };

    InitImage.prototype.bindEvents = function(imgs) {
        if (this.masonry == null) {
            this.masonry = new Masonry("#" + this.params.id);
        } else {
            this.masonry.appended($("#" + this.params.id).children(":not([layout='true'])"));
        }
        imgs.load(function() {
            $(this).removeClass("default_img");
        });
    };

    InitImage.prototype.after = function(imgs) {
        this.$contentElements.each(function() {
            var $content = $(this);
            $content.removeAttr("img-src");
            $content.removeAttr("img-width");
            $content.removeAttr("img-height");
            $content.removeAttr("img-class");
            $content.removeAttr("imageloader");
        });
        $("#" + this.params.id).children(":not([layout='true'])").each(function() {
            $(this).attr("layout", "true");
        });
    };

    (function($) {
        $.fn.unveil = function(threshold, id, callback) {
            var $w = $("#" + id),
                th = threshold || 0,
                retina = window.devicePixelRatio > 1,
                attrib = retina
                    ? "data-src-retina"
                    : "data-src",
                images = this,
                loaded;

            // 绑定unveil事件，加载图片
            this.one("unveil", function() {
                var source = this.getAttribute(attrib);
                source = source || this.getAttribute("data-src");
                if (source) {
                    this.setAttribute("src", source);
                    if (typeof callback === "function"){
						callback.call(this);
					}
                }
            });

            function unveil() {
                // 获取视域中的image
                var inview = images.filter(function() {
                    var $e = $(this);
                    if ($e.is(":hidden"))
                        return;

                    var wt = $w.offset().top,
                        wb = wt + $w.height(),
                        et = $e.offset().top,
                        eb = et + $e.height();

                    return eb >= wt - th && et <= wb + th;
                });

                // 触发unveil事件
                loaded = inview.trigger("unveil");
                // 将已经加载的image从image对象数组中剔除
                images = images.not(loaded);
            }

            // 当窗口滚动的时候触发unveil方法
            $w.on("scroll.unveil resize.unveil lookup.unveil", unveil);
            unveil();

            return this;
        };

        $.fn.bindClick = function(callback) {
            $(this).unbind("click");
            $(this).bind("touchstart", function(event) {
                var clicked = $(this).attr("clicked");
                if (clicked != "true") {
                    var dom = $(this);
                    callback.call(this, event);
                    dom.attr("clicked", "true");
                    setTimeout(function() {
                        dom.removeAttr("clicked");
                    }, 500);
                }
            });
        };

        $.scrollToLoad = function(id, callback) {
            var $w = $("#content-body"),
                th = 100;
            if (!id) {
                $.MessageAlert({content: "$.scrollToLoad参数不正确"});
            }
            var $wrap = null;
            if (typeof id == "string") {
                $wrap = $("#" + id);
            } else if (typeof id == "object") {
                $wrap = $(wrap);
            }
            var $target = $wrap.children().last();

            function unveil() {
                var inview = $target.filter(function() {
                    var $e = $(this);
                    if ($e.is(":hidden"))
                        return;

                    var wb = $w.height() + $w.offset().top,
                        et = $e.offset().top,
                        eb = et + $e.height();
                    return eb <= wb;
                });

                if (inview.length != 0) {
                    callback.call();
                    $target = $wrap.children().last();
                }
            };

            $w.on("scroll.unveil resize.unveil lookup.unveil", unveil);
            if ($target.length == 0) {
                unveil();
            }

            return this;
        };
    })(window.jQuery || window.Zepto);

    /**
	 * 实现abort所有的ajax请求
	 *
	 * @param $
	 */
    (function($) {
        $.each([
            "ajaxSend", "ajaxComplete"
        ], function(i, type) {
            $.fn[type] = function(fn) {
                return this.on(type, fn);
            };
        });
    })(window.jQuery || window.Zepto);
    (function($) {
        var xhrPool = [];
        $(document).ajaxSend(function(e, jqXHR, options) {
            xhrPool.push(jqXHR);
        });
        $(document).ajaxComplete(function(e, jqXHR, options) {
            xhrPool = $.grep(xhrPool, function(x) {
                return x != jqXHR;
            });
        });
        $.abort = function(callback) {
            $.each(xhrPool, function(idx, jqXHR) {
                jqXHR.abort();
            });
            if (callback) {
                callback.apply(this, []);
            }
        };

        /**
		 * NOTICE
		 * 单页模式中不要在onbeforeunload方法中调用$.abort。
		 * HistoryAPI也会触发该方法，造成页面加载中断
		 */
        // var oldbeforeunload = window.onbeforeunload;
        // window.onbeforeunload = function() {
        // 	var r = oldbeforeunload ? oldbeforeunload() : undefined;
        // 	if (r == undefined) {
        // 		$.abort();
        // 	}
        // 	return r;
        // };
    })(window.jQuery || window.Zepto);
});
